﻿#ifndef FILEMANAGER_H
#define FILEMANAGER_H

#include <string>
#include <memory>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include "../nlohmann/json.hpp"
#include <stdint.h>
#include <map>


class FileManager
{
public:
    // 删除拷贝构造函数和拷贝赋值操作符
    FileManager(FileManager const&) = delete;
    FileManager& operator=(FileManager const&) = delete;
    // 提供一个全局唯一的接口
    static FileManager& getInstance() {
        static FileManager instance;
        return instance;
    }
    // check path if exist
    bool checkPath(const std::string& path, bool create = false);


    // init file manager, check if directory exists
    void init();
    // read local file
    std::pair<std::shared_ptr<unsigned char[]>, int> readFromDisk(const std::string& path, uint64_t blockOffset, uint64_t size, bool decrypted = true);
    // write local file
    void writeToDisk(const std::string& path, uint64_t blockOffset, const char* file, uint64_t size, bool encrypted = true);
    // write local file
    void writeToDisk(std::shared_ptr<std::ofstream> ofs, uint64_t blockOffset, const char* file, uint64_t size, bool encrypted = true);


    // guard thread
    void processQueue();

    // register ID and filePath
    void registerID(uint64_t id, const std::string& path, uint64_t fileSize);
    // finish ID
    void finishID(uint64_t id);
    // requery file path according to fileID
    std::string queryFilePath(uint64_t id);
    uint64_t queryFileSize(uint64_t id);

    // commit to queue
    void commitToQueue(const nlohmann::json& data);

    void handleFileBlock(const nlohmann::json& dataJson);

    void setAutoWriteEncrypted(bool encrypted = true);

    const std::string FILES_DIR = "./files";
    const std::string PIC_DIR = "./picture";
    const int FILE_BLOCK_SIZE = 4096;
    const int ENCRYPTED_FILE_BLOCK_SIZE = 4112;

    void stop() {
        // Signal to terminate
        done = true;
        cv.notify_one();
    }
private:
    FileManager() : done(false), encrypted(false) {
    }

    ~FileManager() {

    }


    // converter fileID to filePath;
    std::map<uint64_t, std::pair<std::string, uint64_t>> ID2FileInfo;
    std::map<uint64_t, std::shared_ptr<std::ofstream>> ID2Ofstream;
    std::map<uint64_t, std::shared_ptr<std::mutex>> ID2Lock;

    std::atomic<bool> encrypted;
    std::atomic<bool> done;
    std::queue<nlohmann::json> dataQueue;
    std::mutex mtx;
    std::condition_variable cv;

};

#endif // FILEMANAGER_H
